package com.ai.wxy.spring.web;

import com.ai.spring.common.enums.ResponseCodeEnum;
import com.ai.spring.common.exception.FileTypeMultipartException;
import com.ai.spring.common.util.StringUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.PathMatcher;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 文件上传fesolver
 *
 * @author 石头
 * @Date 2019/11/15
 * @Version 1.0
 **/
@Slf4j
public class FileUploadMultipartResolver extends StandardServletMultipartResolver {
    private final PathMatcher matcher = new AntPathMatcher();
    private List<String> whiteConditions;
    @Setter
    private Boolean zresolveLazily;
    @Setter
    private long maxFileSize;
    @Setter
    private long maxRequestSize;

    public void setWhiteConditionStr(String conditions) {
        whiteConditions = Arrays.asList(StringUtils.split(conditions,","));
    }

    @Override
    public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        super.setResolveLazily(zresolveLazily);

        try {
            MultipartHttpServletRequest multipartHttpServletRequest = super.resolveMultipart(request);
            Collection<List<MultipartFile>> files = multipartHttpServletRequest.getMultiFileMap().values();
            AtomicLong sumFileSize = new AtomicLong(maxRequestSize);
            if (!CollectionUtils.isEmpty(files)){
                files.stream().forEach(datas -> {
                    datas.stream().forEach(file -> {
                        // 验证文件类型
                        String extname = file.getOriginalFilename();
                        if (!audit(extname)){
                            throw new FileTypeMultipartException(ResponseCodeEnum.ERROR_UPLOAD_TYPE);
                        }
                        // 验证上传文件大小
                        long fileSize = file.getSize();
                        if (fileSize > maxFileSize){
                            throw new FileTypeMultipartException(ResponseCodeEnum.ERROR_UPLOAD_MAX);
                        }

                        sumFileSize.getAndSet(sumFileSize.longValue() - fileSize);
                    });
                });
            }

            long leftSize = sumFileSize.get();
            if (leftSize < 0){
                throw new FileTypeMultipartException(ResponseCodeEnum.ERROR_UPLOAD_TMAX);
            }

            return multipartHttpServletRequest;
        }catch (MaxUploadSizeExceededException e) {
            throw new FileTypeMultipartException(ResponseCodeEnum.ERROR_UPLOAD_MAX);
        }catch (FileTypeMultipartException e){
            throw e;
        }catch (Exception e){
            throw new FileTypeMultipartException(ResponseCodeEnum.ERROR_UPLOAD);
        }
    }

    private Boolean audit(String input){
        if (whiteConditions == null || whiteConditions.size() == 0) {
            return Boolean.TRUE;
        }
        // 先转为小写
        final String fileName = input.toLowerCase();
        for (final String pattern : whiteConditions) {
            if (matcher.match(pattern, fileName)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
}
